﻿using System;
using System.Drawing;
using System.Windows.Forms;
using Game;

namespace Memory.WindowsUI
{
    public class FormGameBoard : Form
    {
        private const int k_CardSize = 50;
        private const int k_CardSpacing = 8;
        private const string k_FormTitle = "Memory Game";
        private const string k_CurrentPlayerString = "Current Player: {0}";
        private const string k_PlayerAndScoreString = "{0}: {1} Pair(s)";
        private const string k_GameOverString = "Game Over";
        
        private Engine m_Engine;

        private Label labelCurrentPlayer = new Label();
        private Label labelPlayer1 = new Label();
        private Label labelPlayer2 = new Label();

        private Color m_Player1Color = Color.LimeGreen;
        private Color m_Player2Color = Color.CornflowerBlue;

        public FormGameBoard(GameSettings i_GameSettings)
        {
            m_Engine = new Engine(i_GameSettings);
            
            this.MaximizeBox = false;
            this.FormBorderStyle = FormBorderStyle.FixedSingle;
            this.StartPosition = FormStartPosition.CenterScreen;
            this.Text = k_FormTitle;
            this.Size = new Size(
                (2 * k_CardSpacing) + (m_Engine.Board.Rows * (k_CardSize + k_CardSpacing)),
                (2 * k_CardSpacing) + ((m_Engine.Board.Cols * (k_CardSize + k_CardSpacing)) + (3 * (labelCurrentPlayer.Height + k_CardSpacing))) + k_CardSpacing);
        }
                
        private void m_Engine_PlayerHasScored(object sender, EventArgs e)
        {
            labelPlayer1.Text = string.Format(k_PlayerAndScoreString, m_Engine.Player1.Name.ToString(), m_Engine.Player1.Score.ToString());
            labelPlayer2.Text = string.Format(k_PlayerAndScoreString, m_Engine.Player2.Name.ToString(), m_Engine.Player2.Score.ToString());
        }

        private void m_Engine_TurnMovedToNextPlayer(object sender, EventArgs e)
        {
            labelCurrentPlayer.Text = string.Format(k_CurrentPlayerString, m_Engine.CurrentPlayer.Name.ToString());
            labelCurrentPlayer.BackColor = (m_Engine.CurrentPlayer == m_Engine.Player1) ? m_Player1Color : m_Player2Color;
        }

        private void m_Engine_EndOfGame(object sender, EventArgs e)
        {
            if (m_Engine.Player1.Score != m_Engine.Player2.Score)
            {
                Player winner = (m_Engine.Player1.Score > m_Engine.Player2.Score) ? m_Engine.Player1 : m_Engine.Player2;
                MessageBox.Show(string.Format("{0} has won with {1} pairs!!", winner.Name.ToString(), winner.Score), k_GameOverString, MessageBoxButtons.OK);
            }
            else
            {
                MessageBox.Show("It's a tie!!", k_GameOverString, MessageBoxButtons.OK);
            }

            this.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.Close();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            registerEventHandlers();
            initControls();
        }

        private void registerEventHandlers()
        {
            ////m_Engine.EndOfGame += new EventHandler(m_Engine_EndOfGame);
            m_Engine.TurnMovedToNextPlayer += new EventHandler(m_Engine_TurnMovedToNextPlayer);
            m_Engine.PlayerHasScored += new EventHandler(m_Engine_PlayerHasScored);
        }

        private void initControls()
        {
            initCardButtons();

            labelCurrentPlayer.Text = string.Format(k_CurrentPlayerString, m_Engine.Player1.Name);
            labelCurrentPlayer.Location = new Point(k_CardSpacing, (2 * k_CardSpacing) + (m_Engine.Board.Cols * (k_CardSize + k_CardSpacing)));
            labelCurrentPlayer.AutoSize = true;
            labelCurrentPlayer.BackColor = m_Player1Color;

            labelPlayer1.Text = string.Format(k_PlayerAndScoreString, m_Engine.Player1.Name, m_Engine.Player1.Score);
            labelPlayer1.Location = new Point(labelCurrentPlayer.Location.X, labelCurrentPlayer.Height + labelCurrentPlayer.Location.Y);
            labelPlayer1.AutoSize = true;
            labelPlayer1.BackColor = m_Player1Color;

            labelPlayer2.Text = string.Format(k_PlayerAndScoreString, m_Engine.Player2.Name, m_Engine.Player2.Score);
            labelPlayer2.Location = new Point(labelPlayer1.Location.X, labelPlayer1.Height + labelPlayer1.Location.Y );
            labelPlayer2.AutoSize = true;
            labelPlayer2.BackColor = m_Player2Color;

            this.Controls.AddRange(new Control[] { labelCurrentPlayer, labelPlayer1, labelPlayer2 });
        }

        private void initCardButtons()
        {
            Point anchor = new Point(8, 8);

            for (int i = 0; i < m_Engine.Board.Rows; i++)
            {
                for (int j = 0; j < m_Engine.Board.Cols; j++)
                {
                    Point location = new Point(
                        (i * (k_CardSize + k_CardSpacing)) + anchor.X,
                        (j * (k_CardSize + k_CardSpacing)) + anchor.Y);
                    CardButton currentButton = new CardButton(i, j, m_Engine.Board);
                    currentButton.Location = location;
                    currentButton.Size = new Size(k_CardSize, k_CardSize);
                    currentButton.Click += new EventHandler(currentButton_Click);
                    currentButton.CardChangedStaus += new EventHandler(currentButton_CardChangedStaus);
                    this.Controls.Add(currentButton);
                }
            }  
        }

        private void currentButton_CardChangedStaus(object sender, EventArgs e)
        {
            CardEventArgs args = e as CardEventArgs;
            CardButton button = sender as CardButton;
            Card card = args.BoardPointer.GetCard(button.Coordinates);
            const bool v_IsVisible = true;

            switch (card.Status)
            {
                case Card.eCardStatus.Visible:
                    button.ToggleText(v_IsVisible);
                    button.BackColor = labelCurrentPlayer.BackColor;
                    button.Enabled = false;
                    break;

                case Card.eCardStatus.Invisible:
                    button.ToggleText(!v_IsVisible);
                    button.UseVisualStyleBackColor = true;
                    button.Enabled = true;
                    break;
                
                case Card.eCardStatus.Burned:
                    button.ToggleText(v_IsVisible);
                    button.BackColor = labelCurrentPlayer.BackColor;
                    button.Enabled = false;
                    break;
                default:
                    break;
            }
        }

        private void currentButton_Click(object sender, EventArgs e)
        {
            m_Engine.TakeAMoveFromPlayer((sender as CardButton).Coordinates);
        }
    }
}
